<template>
  <div
    v-loading="isVisualVappShowLoadingProgress && isLoading"
    class="chartMain single-value"
    :class="`${componentStyleClass} ${componentStyle}-Style`"
  >
    <Tooltip ref="Tooltip" :component-style="componentStyle" />
    <AdvancedLinkageToolbar :wid="widgetInstanceId" :config="config" />
    <div
      :id="'chartMain' + chartId"
      v-visual-tooltip="getTooltip(value)"
      class="content"
      :class="componentName"
      :style="{ ...getCssStyle('grid'), ...boxBgColor, height: '100%', '--justify': justifyContent }"
    >
      <div v-if="!isNoData && !isDataAbnormal" class="displayBox-main">
        <div class="single-value-contentBox">
          <div
            :class="
              `contentData box ${config.config.property.selectedStatus ? 'contentData-hover' : ''} ${
                isSelected && config.config.property.selectedStatus ? 'on' : ''
              }`
            "
            @click="toggleSlected()"
          >
            <div v-if="hasIcon === 'withIcon'" class="img">
              <Icon v-if="haveIcon(icon)" :conf="icon" :style="getCssStyle({ marginRight: 10 })" />
              <img
                v-else-if="imgUrl || thresholdStyle.imgUrl"
                :src="thresholdStyle.imgUrl ? thresholdStyle.imgUrl : imgUrl"
                :style="style.img"
              />
            </div>
            <div v-if="componentName === 'single_value_vertical_icon'" class="text">
              <div class="block1" :style="style.block1">
                <span class="value" :style="thresholdStyle.value">
                  {{ setNull(value) }}
                </span>
                <span
                  class="value"
                  :style="{
                    ...getCssStyle('unit'),
                    ...thresholdStyle.unit,
                  }"
                >
                  {{ ' ' + unit }}
                </span>
              </div>
              <span class="title" :style="getCssStyle('name')">
                {{ title }}
              </span>
            </div>
            <div v-if="componentName === 'single_value_vertical'">
              <div class="block1">
                <span class="value" :style="thresholdStyle.value">
                  {{ value }}
                </span>
                <span
                  class="unit"
                  :style="{
                    ...getCssStyle('unit'),
                    ...thresholdStyle.unit,
                  }"
                >
                  {{ ' ' + unit }}
                </span>
              </div>
              <span class="title" :style="getCssStyle('name')">
                {{ title }}
              </span>
            </div>
            <div v-if="componentName === 'single_value_horizontal_icon'" class="text">
              <span class="title" :style="getCssStyle('name')">
                {{ title }}
              </span>
              <span class="value" :style="thresholdStyle.value">
                {{ value }}
              </span>
              <span
                class="value"
                :style="{
                  ...getCssStyle('unit'),
                  ...thresholdStyle.unit,
                }"
              >
                {{ ' ' + unit }}
              </span>
            </div>
          </div>
        </div>
      </div>
      <NoData
        :isNoData="isNoData"
        :boxBgColor="boxBgColor"
        :noDataPromptType="config.config.property.noDataPromptType"
        :noDataPrompt="config.config.property.noDataPrompt"
      />
      <AbnormalData :isDataAbnormal="isDataAbnormal" :boxBgColor="boxBgColor" :abnormalType="abnormalType" />
    </div>
  </div>
</template>
<script>
import AdvancedLinkageToolbar from '@/components/common/advanced-linkage/advanced-linkage-toolbar.vue';
import Icon from '@/components/common/icon/icon.vue';
import chartBase from '@/mixin/chart-base.js';
import emitComponentBase from '@/mixin/emit-component-base.js';
import componentValueBase from '@/mixin/component-value-base.js';
import { EMIT_PARAMS_OBJ } from '@/utils/constant';
import iconChartBase from '@/mixin/icon-chart-base.js';
import dataModel from '@/models/panel-config-data.js';
import { convertValue, getThemeColors, numFormat } from '@/utils/util';
import { nextTick } from 'vue';
import NoData from '../common/no-data/no-data.vue';
import AbnormalData from '../common/abnormal-data/abnormal-data.vue';
import Tooltip from '../common/tooltip/tooltip.vue';
import colorGroup from './config/colorGroup';
import config from './config/config';
import dfCssStyle from './config/cssStyle-default.js';
import EventBus from '@/event-bus/EventBus.js';

export default {
  name: 'SingleValue',
  components: { Tooltip, NoData, Icon, AdvancedLinkageToolbar, AbnormalData },
  mixins: [chartBase, iconChartBase, componentValueBase, emitComponentBase],
  props: ['pareentId', 'widgetId', 'widgetInstanceId', 'widgetName', 'identifier', 'layout', 'w', 'h'],
  data() {
    return {
      componentName: '',
      isLoading: false,
      isNoData: false,
      orgConfig: [],
      isShow: true,
      chartId: '',
      config: null,
      value: '',
      title: '',
      unit: '',
      nullSet: '',
      icon: '',
      style: {
        light: {
          value: { color: '#00AAFF' },
          title: { color: '#696969' },
          unit: { color: '#00AAFF' },
        },
        dark: {
          value: { color: '#01F5F5' },
          title: { color: '#A4A9AE' },
          unit: { color: '#01F5F5' },
        },
        real: {
          value: { color: '#01F5F5' },
          title: { color: '#A4A9AE' },
          unit: { color: '#01F5F5' },
        },
        img: {},
        imgDiv: {},
        title: {},
        block1: {},
        noData: {},
      },
      isSelected: false,
      componentStyle: window._adoPremise.uc.theme,
      hasIcon: 'withoutIcon',
      textComposition: '',
      imgUrl: '',
      dfCssStyle,
    };
  },
  computed: {
    compoutedItem() {
      const { property } = this.config.config;
      return {
        alias: '',
        icon: this.hasIcon === 'withIcon' ? this.imgUrl : '',
        iconSmall: property.iconSmall,
        imgUrl: this.hasIcon === 'withIcon' ? this.imgUrl : '',
        index: 0,
        name: this.title,
        unit: property.unit,
        value: this.value,
      };
    },
    thresholdStyle() {
      const obj = {
        imgUrl: '',
        value: this.getCssStyle('value'),
        unit: this.getCssStyle('unit'),
      };

      const { thresholdDataType, isThreshold, threshold } = this.config.config.property;
      if (isThreshold) {
        if (thresholdDataType === 'number') {
          threshold.map(child => {
            if (
              this.value !== null &&
              this.getValueNum(this.value) >= child.min &&
              this.getValueNum(this.value) < child.max
            ) {
              obj.value.color = child.color;
              obj.unit.color = child.color;
              this.hasIcon === 'withIcon' && child.imgUrl ? (obj.imgUrl = child.imgUrl) : null;
            }
          });
        } else {
          threshold.map(child => {
            if (this.value !== null && this.value === child.text) {
              obj.value.color = child.color;
              obj.unit.color = child.color;
              this.hasIcon === 'withIcon' && child.imgUrl ? (obj.imgUrl = child.imgUrl) : null;
            }
          });
        }
      }
      if (!obj.value.color) {
        // value默认字体颜色
        obj.value.color = this.getValByCompStl('#2d8cf0', '#2df7ff', '#eee');
      }
      return obj;
    },
    justifyContent() {
      const { justify } = this.config.config.property;
      return justify;
    },
  },
  watch: {
    w() {
      nextTick(() => {
        this.calcUnitRect();
      });
    },
    h() {
      nextTick(() => {
        this.calcUnitRect();
      });
    },
  },
  created() {
    this.orgConfig = config;
    this.config = JSON.parse(JSON.stringify(this.orgConfig));

    this.chartId = `${this.widgetInstanceId}_01`;
  },
  methods: {

    /**
     * 计算容器的最小宽高 实现自适应
     */
    async calcUnitRect() {
      this.calcing = true;
      const compnt = document.getElementById(`chartMain${this.chartId}`);
      if (!compnt) {
        return;
      }
      const contentBox = compnt.getElementsByClassName('displayBox-main')[0];
      const arrW = [];
      const arrH = [];
      contentBox.style = {};
      contentBox.style.minWidth = 'auto';
      contentBox.style.minHeight = 'auto';
      const boxWidth = compnt.offsetWidth || 0;

      const units = compnt.getElementsByClassName('single-value-contentBox');
      for (let i = 0; i < units.length; i++) {
        units[i].style = {};
        units[i].style.minWidth = 'auto';
        units[i].style.minHeight = 'auto';
        const unitWidth = units[i].offsetWidth || 0;
        if (boxWidth > unitWidth) {
          units[i].style.width = 'auto';
        } else {
          units[i].style.width = 'min-content';
        }
      }

      for (let i = 0; i < units.length; i++) {
        const contentData = units[i].getElementsByClassName('contentData')[0];
        if (contentData) {
          arrW.push(contentData.offsetWidth);
          arrH.push(contentData.offsetHeight);
        }
      }
      arrW.sort((a, b) => b - a);
      arrH.sort((a, b) => b - a);
      contentBox.style.minHeight = `${arrH[0]}px`;
      contentBox.style.minWidth = `${arrW[0]}px`;

      this.calcing = false;
    },

    // 初始加载时 以及 编排面更改配置时 触发
    loadWidget(pageStatus) {
      this.pageStatus = pageStatus;
      this._updateConfigProperty();
      this.updateImgUrlSingleValue();

      this.updateConfigData();

      if (window.isLocalEnv || this.emitComponentStatus) {
        this.updateParams(pageStatus);

        // 实时通讯组件不主动请求数据
        if (!this.isRealTime) {
          this.debounceGetData();
        }
      }
      this.afterLoadWidget();
    },
    toggleSlected() {
      this.isSelected = !this.isSelected;

      const { selectedStatus } = this.config.config.property;

      // 高级事件联动
      const value = this.getValueNum(this.value);
      if (selectedStatus) {
        if (this.isSelected) {
          this.sendAllMessages({ value });
          this.sendAdvancedLinkagge({ value });
        } else {
          this.sendEmptyMessages();
          this.clearWidAdvLinkage();
        }
      } else {
        this.sendAllMessages({ value });
        this.sendAdvancedLinkagge({ value });
      }
      this.executeAction('', { value });
    },

    sendAllMessages({ value }) {
      this.isBlank = false;
      const configParameters = this.config.events[0].parameters;
      const parameters = {
        [configParameters[0].key]: value,
      };
      const keys = [configParameters[0].key];
      const eventItem = this.orgConfig.events[0];
      const evtKey = eventItem.key;
      const outObj = {};
      outObj[EMIT_PARAMS_OBJ] = {
        eventKey: this.config.events[0].key,
        keys,
        parameters,
        type: 'terms',
        widgetInstanceId: this.widgetInstanceId,
        componentName: 'single-value',
        sendTime: new Date().getTime(),
      };
      this.beforeEmit(outObj);
      if (this.widgetInstanceId) {
        this.vsEmit(evtKey, outObj);
      } else {
        EventBus.$emit(evtKey, outObj);
      }
    },

    _updateConfigProperty() {
      this.updateConfigProperty();
      const { textComposition } = this.config.config.property;
      this.hasIcon = this.config.config.property.hasIcon;

      if (textComposition === 'horizontal') {
        this.componentName = 'single_value_horizontal_icon';
      } else {
        if (this.hasIcon === 'withIcon') {
          this.componentName = 'single_value_vertical_icon';
        } else {
          this.componentName = 'single_value_vertical';
        }
      }
      this.unit = this.config.config.property.unit;
      this.nullSet = this.config.config.property.nullSet;
      this.icon = this.config.config.property.icon;
      this.textComposition = textComposition;

      this.updateComponentByResolution();
      this.updateValueStyle();
    },

    // 根据分辨率来更新组件
    updateComponentByResolution() {
      const { iconSize } = this.config.config.property;
      nextTick(() => {
        const paddingLR = 10;
        let imgWidth; // 1920下图片默认大小
        this.style[this.componentStyle].title.paddingRight = 0;
        this.style.block1.paddingBottom = 0;
        if (this.componentName === 'single_value_horizontal_icon') {
          imgWidth = 32;
          this.style[this.componentStyle].title.paddingRight = `${convertValue(18)}px`;
        } else if (this.componentName === 'single_value_vertical_icon') {
          imgWidth = 60;
          this.style.block1.paddingBottom = `${convertValue(14)}px`;
        } else {
        }
        if (imgWidth) {
          this.style.imgDiv = {
            padding: `0 ${convertValue(paddingLR)}px`,
            width: `${convertValue(iconSize.width || imgWidth)}px`,
          };
          this.style.img = {
            width: `${convertValue(iconSize.width || imgWidth)}px`,
            height: `${convertValue(iconSize.height || imgWidth)}px`,
            marginRight: `${convertValue(paddingLR)}px`,
          };
        }

        this.style = JSON.parse(JSON.stringify(this.style));
      });
    },
    updateValueStyle() {
      const { componentStyle, color } = this.config.config.property;

      // 颜色方案，分别对应着背景色，值颜色，标题颜色
      const colorScheme = getThemeColors(color, colorGroup[componentStyle]);

      nextTick(() => {
        this.style[componentStyle].value.color = colorScheme[1];
        this.style[componentStyle].unit.color = colorScheme[1];
        this.style[componentStyle].title.color = colorScheme[2];
      });
    },

    // 接收xvue发来的实时数据
    handleRealTimeCommunication(realTimeData) {
      const result = this.getResult(realTimeData);
      if (this.isNoData || this.autoRefreshIsSameRes(result)) {
        this.isLoading = false;
        return;
      }
      this.handleSingleValueResult(result);
      this.isLoading = false;
    },

    // api请求获取图表数据
    getChartData() {
      const { data } = this.config.config;

      // 如果dataSourceType为静态数据,把数据放到Vuex，发出事件，然后退出
      if (data.dataSourceType === 'staticData') {
        const result = this.getStaticData();
        this.handleSingleValueResult(result);

        // 重置数据异常状态
        this.resetAbnormalType();
        return;
      }

      // api请求，拿到数据
      if (data.dataSourceType) {
        this.isNoData = false;
        this.isLoading = true;
        this.autoRefresh();
        const method = `getChartData${data.dataSourceType}`;
        const params = this.getCorrectParams(this.params, data.dataSourceType);
        dataModel[method](params, data)
          .then(result => {
            // 重置数据异常状态
            this.resetAbnormalType();
            this.reportIfFieldsError(this.getParams()?.propertyMapping, result);
            if (this.autoRefreshIsSameRes(result)) {
              return;
            }
            this.handleSingleValueResult(result);
          })
          .catch(err => {
            this.handleChartDataError(err);
          })
          .finally(() => {
            this.isLoading = false;
          });
      } else {
        // 如果在用户面，则给提示
        if (this.$route.name === 'userHomePage') {
          this.$message({
            message: this.$demoi18n('view.dataSourceTypeEmpty'),
            type: 'warning',
          });
        }
      }
    },
    handleSingleValueResult(result) {
      const { thresholdDataType, isThreshold, threshold } = this.config.config.property;
      this.sendDataToConfig(result);
      this.value = '';
      if (!result || result.length === 0) {
        this.isNoData = true;
        return;
      }
      if (result[0].value === null) {
        this.value = numFormat(this.nullSet, true);
      } else {
        this.value = numFormat(result[0].value, true);
      }
      if (isThreshold) {
        if (thresholdDataType === 'number') {
          threshold.map(child => {
            if (
              this.value !== null &&
              this.getValueNum(this.value) >= child.min &&
              this.getValueNum(this.value) < child.max
            ) {
              this.hasIcon === 'withIcon' && child.icon ? (this.icon = child.icon) : null;
            }
          });
        } else {
          threshold.map(child => {
            if (this.value !== null && this.value === child.text) {
              this.hasIcon === 'withIcon' && child.icon ? (this.icon = child.icon) : null;
            }
          });
        }
      }
      nextTick(() => {
        this.calcUnitRect();
      });
    },
    getTooltip(value) {
      return {
        config: this.config.config.property.tooltip || {},
        vars: {
          value: value,
        },
        params: this.params,
        parentComp: this,
      };
    },
    setNull(val) {
      if (!this.config) {
        return val;
      }
      if (val) {
        return val;
      }
      return this.config.config.property.nullSet;
    },
  },
};
</script>
<style lang="less" scoped>
// 图表通用样式，主要有黑色loading 和 黑色 ‘没有数据’，样式名需一致
@import '../../common/chart.less';
</style>
<style lang="less" scoped>
@import './config/theme.less';
.single-value {
  .content {
    width: 100%;
    height: max-content;
    text-align: center;
    margin: 0 auto;
    overflow: auto;
    .displayBox-main {
      display: flex;
      min-width: 100%;
      min-height: 100%;
      overflow: hidden;
      height: 100%;
      width: 100%;
      justify-content: var(--justify);
      align-items: center;
    }
  }

  .single-value-contentBox {
    width: min-content;
    height: max-content;
    display: flex;
  }

  .box {
    display: flex;
    justify-content: center;
    align-items: center;
    width: auto;
    height: auto;
    &.contentData-hover:hover {
      background-color: var(--content-hover-bg-color);
    }
    &.on {
      background-color: var(--box-on-bg-color);
    }
    .img {
      display: flex !important;
      justify-content: center;
      align-items: center;
    }
  }

  .single_value_horizontal_icon {
    .text {
      display: flex;
      align-items: center;
      .value {
        font-size: 30px;
        font-weight: bolder;
      }
      .title {
        padding-right: 18px;
        font-size: 18px;
      }
    }
  }
  .single_value_vertical_icon {
    .text {
      padding: 0 10px;
      display: inline-block;
      .block1 {
        padding-bottom: 14px;
      }
      .value {
        font-size: 28px;
        font-weight: bolder;
      }
      .title {
        font-size: 17px;
      }
    }
  }
  .single_value_vertical {
    .block1 {
      padding-bottom: 14px;
    }
    .value {
      font-weight: bolder;
      font-size: 39px;
    }
    .title {
      font-size: 18px;
    }
  }
}
</style>
